Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added .env support #2164

Closed
wants to merge 3 commits into from
Closed

Added .env support #2164

wants to merge 3 commits into from

Conversation

mitsuhiko
Copy link
Contributor

This will instruct Flask to read .env files and then to load the
environment variables from there. Additionally it automatically
changes the working directory to the path the .env is contained in.

@@ -120,6 +120,47 @@ def find_default_import_path():
return app


def find_dotenv():
here = os.getcwd()
while 1:

This comment was marked as off-topic.

This comment was marked as off-topic.

if not line or line[:1] == '#' or '=' not in line:
continue
key, value = line.split('=', 1)
_set_env(key, value)

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

if not line or line[:1] == '#' or '=' not in line:
continue
key, value = line.split('=', 1)
_set_env(key, value)

This comment was marked as off-topic.

This comment was marked as off-topic.

with open(path, 'rb') as f:
for line in f:
line = line.strip()
if not line or line[:1] == '#' or '=' not in line:

This comment was marked as off-topic.

This comment was marked as off-topic.

Copy link
Contributor

@untitaker untitaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM though I really want tests for this.

with open(path, 'rb') as f:
for line in f:
line = line.strip()
if not line or line[:1] == '#' or '=' not in line:

This comment was marked as off-topic.

@mitsuhiko
Copy link
Contributor Author

Yeah, tests will come if we like this behavior.

@untitaker
Copy link
Contributor

In case it gets lost: #2164 (comment)

@RonnyPfannschmidt
Copy link
Contributor

isnt there a library for env files? imho flask shouldnt reimplement

@mitsuhiko
Copy link
Contributor Author

@RonnyPfannschmidt i'm not going to pull in a one liner dependency here.

@untitaker the behavior here is consistent with other libraries that implement .env loading.


FLASK_APP=/path/to/hello.py
FLASK_DEBUG=1

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

@mitsuhiko
Copy link
Contributor Author

So maybe we put the conversation back to where this started: the goal was to make it easier during development to refer to the current Flask app. I do not see this as a feature for production. However let's see if we can figure out the production case as well.

How does one refer to their own app in production without exporting env variables?

@miguelgrinberg
Copy link
Contributor

miguelgrinberg commented Jan 29, 2017

@mitsuhiko I agree, good idea to pull back a bit.

I think referring to the app instance should work in the same way for development and production, I don't see why the methods should differ, since the app instance is the same in all cases. And there is also the complication of app factories, which are not friendly to FLASK_APP (#2027).

What I do, is define a wsgi.py file for each of my projects. I started adopting this as a convention, so I can have a hardcoded FLASK_APP=wsgi.app set in my .profile file and switch from app to app without worries. Would you consider implementing one or more sensible defaults for FLASK_APP? I think wsgi.application and wsgi.app are fairly common and could be defaults.

@jeffwidman
Copy link
Contributor

I've also commonly seen .env files used to store secrets, and managed via Ansible Vault or similar.

@@ -11,6 +11,9 @@ Major release, unreleased
- Make `app.run()` into a noop if a Flask application is run from the
development server on the command line. This avoids some behavior that
was confusing to debug for newcomers.
- The `flask` command line tool now loads a `.env` file when it discovers
one. When it finds one it will change into that folder before starting

This comment was marked as off-topic.

This comment was marked as off-topic.

@davidism
Copy link
Member

davidism commented Jan 30, 2017

How does one refer to their own app in production without exporting env variables?

I do it by not using the flask command directly. Instead, I install an entry point to the project's own FlaskGroup, configured appropriately, and expect the project to be installed in the env both in development and production.

cli = FlaskGroup(create_app=create_app)
setup(
    ...,
    entry_points={
        'console_scripts': [
            'myapp=myapp.cli:cli.main',
        ],
    },
    ...,
)
FLASK_DEBUG=1 myapp run

@davidism
Copy link
Member

davidism commented Jan 30, 2017

One option for making this play nicer with the factory pattern is to allow making a call in the FLASK_APP var. Gunicorn and uWSGI allow this. gunicorn myapp.app:create_app(where='dev')

@nickjj
Copy link
Contributor

nickjj commented Jan 30, 2017

@mitsuhiko

How does one refer to their own app in production without exporting env variables?

Is this a valid question? Because you could also say "how does one refer to their own app in production without creating an instance/settings.py file", and then it becomes the same thing.

At the end of the day, this file needs to be on the production box for the app to be usable.

Personally, I use Docker and it has mechanisms for supplying an .env file of my choosing, then it makes those env variables available to the Flask app with no extra dirty work.

Without Docker, I would likely drop an environment file in /etc/default/fooapp which is the defaco-standard place on a Debian system to write out app-level environment variables. Then I would source that file in whatever init system I use.

In other words, in both development and production this env file would be available to the Flask app.

If this feature does end up being implemented, please let us configure the .env filename.

I would much prefer to use env variables instead of config/instance files because it plays much nicer when trying to scale applications on infrastructures that let you define clusters of servers, but then can define env variables in a central area (outside of each individual host), and then they become available to all hosts without worrying about the logistics of getting an env file on the system.

This could be done now of course, but it kind of goes against the norm which is to use config/instance based config files instead of env variables.

@justanr
Copy link

justanr commented Jan 31, 2017

If I'm understanding this correctly, this would only read the .env when executed from the CLI, correct? That seems like it setting developers up for mistakes, I can see the bug reports and SO questions now: "Flask loads my .env file when I run the development server, but not when executed from uWSGI"

If this was going to be added, I'd rather see it implemented into either the Flask class or config class to at least be consistent between server options.

@greyli
Copy link
Member

greyli commented Apr 7, 2017

I did it by adding this into virtual environment's activate script, the variable will be set automatically when the virtual environment was activated. No multiple application crashing, no new file.

For example:
Unix Bash: venv/bin/activate:

FLASK_APP=foo.py
export FLASK_APP

Windows CMD.exe: venv\Scripts\activate.bat:

set "FLASK_APP=foo.py" 
:END

@untitaker
Copy link
Contributor

I don't recommend editing activate scripts.

@greyli
Copy link
Member

greyli commented Apr 7, 2017

@untitaker More detail?

@untitaker
Copy link
Contributor

I already elaborated in the PR you sent. You are editing random files which will get overwritten if you recreate the virtualenv (e.g. because it grew too big, or because a Python upgrade trashed it).

@davidism
Copy link
Member

davidism commented Apr 7, 2017

How about adding an entry point in setup.py to tell the flask command where the app is, similar to how we can add extra commands? Since we're encouraging the use of setup.py anyway, might as well take advantage. Not sure how we would handle multiple packages with the entry point though, if that ever comes up.

@untitaker
Copy link
Contributor

See #2234 (comment)

@davidism
Copy link
Member

davidism commented Apr 7, 2017

I'm leaning on the side of rejecting this. I agree that it would cause confusion, and we already have a documented way to set the env when working locally.

@untitaker
Copy link
Contributor

untitaker commented Apr 7, 2017 via email

@davidism davidism mentioned this pull request Jul 15, 2017
@davidism davidism deleted the feature/dotenv branch July 16, 2017 20:55
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.